BlueMinimap = CreateFrame("Frame")
BlueMinimap:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end)

local _G = _G
local sin = _G.sin
local cos = _G.cos
local mathRad = _G.math.rad
local mathSine = _G.math.sin
local mathCosine = _G.math.cos
local sort = _G.sort
local pairs = _G.pairs
local ipairs = _G.ipairs
local select = _G.select
local tinsert = _G.table.insert
local GetAddOnInfo = _G.GetAddOnInfo
local IsAddOnLoaded = _G.IsAddOnLoaded
local MouseIsOver = _G.MouseIsOver
local UnitName = _G.UnitName
local UnitClass = _G.UnitClass

function BlueMinimap:OnInit()
	MinimapCluster:ClearAllPoints()
	MinimapCluster:SetPoint("TOPRIGHT", -10, -15)
	self:HiddenMinimapElements()
	self:CreateBorder()
	self:SetWheelZoom()
	if select(2, GetAddOnInfo("BlueBlizz")) then
		self:SetMinimapButton()
	end
end

function BlueMinimap:HiddenMinimapElements()
	MinimapBorderTop:Hide()
	if MinimapToggleButton then
		MinimapToggleButton:Hide()
	end
	MinimapZoneText:Hide()
	MinimapZoneTextButton:Hide()
	MinimapZoomIn:Hide()
	MinimapZoomOut:Hide()
	MiniMapWorldMapButton:Hide()
	GameTimeFrame:Hide()
	MinimapBorder:Hide()
end

function BlueMinimap:CreateBorder()
	MinimapBackdrop = CreateFrame("Frame", "BlueMinimapBackdrop", Minimap)
	MinimapBackdrop:SetFrameStrata("BACKGROUND")
	MinimapBackdrop:SetFrameLevel(MinimapBackdrop:GetFrameLevel() - 1)
	MinimapBackdrop:SetAllPoints()
	MinimapBackdrop.updateTime = 1 / 60
	MinimapBackdrop.updateTimer = 0
	MinimapBackdrop.border = {
		self:CreateBorderTexture("SPELLS\\AURARUNE256.BLP", 1.4, 0.31, 0.48, 1, 1, -0.25),
		self:CreateBorderTexture("SPELLS\\AuraRune_A.blp", 2.1, 0.196, 0.29, 1, 0.38, 0.5),
	}
	MinimapBackdrop:SetScript("OnUpdate", function(self, timer)
		self.updateTimer = self.updateTimer + timer
		if self.updateTimer >= self.updateTime then
			self.updateTimer = 0
			for _, texture in ipairs(self.border) do
				texture:Rotate()
			end
			if self.hasButtons then
				self.isOver2, self.isOver = self.isOver
				for _, frame in ipairs(self.overCheck) do
					if MouseIsOver(frame) then
						self.isOver = true
						break
					end
				end
				if self.isOver ~= self.isOver2 then
					self.isOver2 = self.isOver
					if self.isOver then
						UIFrameFadeOut(self, 0.25, self:GetAlpha(), 1)
					else
						UIFrameFadeIn(self, 0.25, self:GetAlpha(), 0)
					end
				end
			end
		end
	end)
end

local function rotate(self, reset)
	self.angle = (self.angle or 0) - (self.speed or 0)
	local s, c = sin(self.angle), cos(self.angle)
	self:SetTexCoord(0.5 - s, 0.5 + c, 0.5 + c, 0.5 + s, 0.5 - c, 0.5 - s, 0.5 + s, 0.5 - c)
end

function BlueMinimap:CreateBorderTexture(texture, scale, r, g, b, a, rotateSpeed)
	local t = Minimap:CreateTexture()
	t:SetWidth(180 * scale)
	t:SetHeight(180 * scale)
	t:SetPoint("CENTER")
	t:SetTexture(texture)
	t:SetBlendMode("ADD")
	t:SetDrawLayer("ARTWORK")
	t:SetVertexColor(r, g , b, a)
	t.speed = rotateSpeed
	t.Rotate = rotate
	t:Rotate()
	return t
end

function BlueMinimap:SetWheelZoom()
	Minimap:EnableMouseWheel()
	Minimap:SetScript("OnMouseWheel", function(self, wheel)
		if wheel == -1 and self:GetZoom() > 0 then
			Minimap_ZoomOutClick()
		elseif wheel == 1 and self:GetZoom() < self:GetZoomLevels() then
			Minimap_ZoomInClick()
		end
	end)
end

function BlueMinimap:SetMinimapButton()
	--[=[
	local mapButtons = {
		{ "InvenRaidFrames2MapButton", "InvenRaidFrames2" },
		{ "InvenCraftInfoMapButton", "InvenCraftInfo" },
		{ "BlueItemInfo2MapButton", "BlueItemInfo2" },
		{ "InvenBuffCheckMapButton", "InvenBuffCheck" },
		{ "InvenSimulatorMapButton", "InvenSimulator" },
		{ "MiniMapBattlefieldFrame" },
		{ "MiniMapVoiceChatFrame" },
		{ "FeedbackUIButton", "Blizzard_FeedbackUI" },
		{ "BlueGearManagerMapButton", "BlueGearManager" },
		{ "MiniMapLFGFrame" },
	}
	MinimapBackdrop.hasButtons = true
	MinimapBackdrop.overCheck = { MinimapBackdrop }
	MinimapBackdrop:SetAlpha(0)
	self.buttons, self.buttonOrders, self.buttonQuee, self.buttonNum = {}, {}, {}, 0
	for index, button in ipairs(mapButtons) do
		self.buttonOrders[button[1]] = index
		if button[2] then
			if select(2, GetAddOnInfo(button[2])) then
				self.buttonQuee[button[1]] = true
			else
				self.checkAddOns = self.checkAddOns or {}
				self.checkAddOns[button[2]] = button[1]
				self:RegisterEvent("ADDON_LOADED")
			end
		elseif _G[button[1]] then
			self.buttonQuee[button[1]] = true
		end
	end
	self.updateTimer = 1
	self:SetScript("OnUpdate", self.MinimapButtonFinder)
	]=]
end

local function buttonSort(a, b)
	if a:IsShown() and b:IsShown() then
		return BlueMinimap.buttonOrders[a:GetName()] < BlueMinimap.buttonOrders[b:GetName()]
	elseif a:IsShown() then
		return true
	end
end

function BlueMinimap:UpdateButtonOrder(angle)
	sort(self.buttons, buttonSort)
	for index, button in ipairs(self.buttons) do
		if button:IsShown() then
			button.angle = -(index - 1) * 19 - 45
			if button.angle > 360 then
				button.angle = button.angle - 360
			elseif button.angle < 0 then
				button.angle = button.angle + 360
			end
			button:ClearAllPoints()
			button:SetPoint("CENTER", MinimapBackdrop, "CENTER", mathCosine(mathRad(button.angle)) * 80, mathSine(mathRad(button.angle)) * 80 - 1)
		else
			break
		end
	end
end

local function isEmptyTable(table)
	for _ in pairs(table) do
		return nil
	end
	return true
end

local function checkToggleButton()
	BlueMinimap:UpdateButtonOrder()
end

function BlueMinimap:MinimapButtonFinder(timer)
	self.updateTimer = self.updateTimer + timer
	if self.updateTimer > 1 then
		self.updateTimer = 0
		if isEmptyTable(self.buttonQuee) then
			self:Hide()
		else
			self.buttonNum = #self.buttons
			for button in pairs(self.buttonQuee) do
				if _G[button] then
					self.buttonQuee[button] = nil
					button = _G[button]
					hooksecurefunc(button, "Show", checkToggleButton)
					hooksecurefunc(button, "Hide", checkToggleButton)
					button:RegisterForDrag(nil)
					button:SetParent(MinimapBackdrop)
					tinsert(self.buttons, button)
					tinsert(MinimapBackdrop.overCheck, button)
				end
			end
			if self.buttonNum ~= #self.buttons then
				self.buttonNum = #self.buttons
				self:UpdateButtonOrder()
			end
		end
	end
end

function BlueMinimap:ADDON_LOADED(addon)
	if self.checkAddOns[addon] then
		self.buttonQuee[self.checkAddOns[addon]] = true
		self.checkAddOns[addon] = nil
		if isEmptyTable(self.checkAddOns) then
			self:UnregisterEvent("ADDON_LOADED")
		end
		self:Show()
	end
end

BlueMinimap:OnInit()